package com.ruoyi.business.service.impl;

import com.ruoyi.business.service.IProcessService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

/**
 * Created by heiyan
 */
@Service
public class ProcessServiceImpl implements IProcessService {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;


    @Override
    public Deployment deploy(String filePath) throws IOException {
        Deployment deploy = null;
        if (filePath.endsWith("zip")) {
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(filePath));
            deploy = repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream)
                    .deploy();
        } else if (filePath.endsWith("bpmn")) {
            deploy = repositoryService.createDeployment()
                    .addInputStream(filePath,new FileInputStream(filePath))
                    .deploy();
        }
        return deploy;
    }

    @Override
    public ProcessDefinition selectProcessDefinitionByDeploymentId(String deploymentId) {
        return repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
    }

    @Override
    public InputStream getResourceAsStream(String deploymentId, String resourceName) {
        return repositoryService.getResourceAsStream(deploymentId,resourceName);
    }

    @Override
    public InputStream getProcessImage(String processDefinitionId,
                                       List<String> highLightedActivities,
                                       List<String> highLightedFlows) {
        BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
        ProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        //generateDiagram(流程模型,需要高亮的节点,需要高亮的线条,后面三个参数都表示是字体)
        InputStream inputStream = generator.generateDiagram(model, highLightedActivities, highLightedFlows,"宋体","宋体","宋体");
        return inputStream;
    }

    @Override
    public Task getTaskByProcessInstanceId(String id) {
        return taskService.createTaskQuery().processInstanceId(id).singleResult();
    }

    @Override
    public ProcessInstance startProcessInstance(String definitionKey, String businessKey, Map<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(definitionKey,businessKey,variables);
    }

    @Override
    public void addCandidateUser(Task currentTask, Long userId) {
        taskService.addCandidateUser(currentTask.getId(),String.valueOf(userId));
    }



    @Override
    public InputStream getProcessImageByInstanceId(String instanceId) {
        //获取流程实例ID
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        //获取bqmnModel，主要描述节点，连线的信息
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        //定义绘制图形对象
        DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(processInstance.getId());
        //第一个参数：bpmnModel 第二个参数：需要高亮的节点集合  第三个参数：需要高亮连线集合
        InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, activeActivityIds, Collections.EMPTY_LIST,"宋体","宋体","宋体");
        return inputStream;
    }

    @Override
    public void deleteProcessInstance(String instanceId) {
        runtimeService.deleteProcessInstance(instanceId,"撤销申请");
    }

    @Override
    public Long getTodoTaskCount(String definitionKey, String userId) {
        return taskService.createTaskQuery().processDefinitionKey(definitionKey).taskCandidateUser(userId).count();
    }

    @Override
    public List<Task> selectTodoTaskList(String definitionKey, String userId, Integer startNum, Integer pageSize) {
        return taskService.createTaskQuery()
                .processDefinitionKey(definitionKey)
                .taskCandidateUser(userId)
                .orderByTaskCreateTime()
                .asc()
                .listPage(startNum,pageSize);
    }

    @Override
    public ProcessInstance getTaskByProcessInstanceById(String processDefinitionId) {
        return runtimeService.createProcessInstanceQuery().processInstanceId(processDefinitionId).singleResult();
    }

    @Override
    public Task getTaskByTaskId(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    @Override
    public void claimAndComplete(Task task, String userId, Boolean auditStatus, String comment) {
        String commentStr = auditStatus?"[同意]":"[拒绝]";
        commentStr+=comment;
        //给当前任务添加批注信息
        taskService.addComment(task.getId(),task.getProcessInstanceId(),commentStr);
        //认领任务
        taskService.claim(task.getId(),userId);
        //执行任务，把流程变量传入
//        Map<String,Object> variables = new HashMap<>();
//        variables.put(task.getTaskDefinitionKey(),auditStatus);
//        taskService.complete(task.getId(),variables);
        //第一次设置直接加入流程变量中  第二次如果key名字相同 把流程变量覆盖
        taskService.setVariable(task.getId(),task.getTaskDefinitionKey(),auditStatus);
        taskService.complete(task.getId());
    }

    @Override
    public void claimAndComplete(Task task, String userId, String comment) {

        //给当前任务添加批注信息
        taskService.addComment(task.getId(),task.getProcessInstanceId(),comment );
        //认领任务
        taskService.claim(task.getId(),userId);
        //执行任务，把流程变量传入
        taskService.complete(task.getId());
    }

    @Override
    public void setVariable(String taskId, String key, long value) {
//        runtimeService.setVariable(processInstanceId,key,value);
        taskService.setVariable(taskId,key,value);
    }

    @Override
    public long getHistoricTaskCount(String definitionKey, String userId) {
        return historyService.createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .count();
    }

    @Override
    public List<HistoricTaskInstance> selectHistoricTaskList(String definitionKey, String userId, Integer startNum, Integer pageSize) {
        return historyService.createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .orderByHistoricTaskInstanceEndTime()//按照任务完成的结束时间进行排序
                .desc()
                .listPage(startNum,pageSize);
    }


    @Override
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
        return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
    }

    @Override
    public List<HistoricActivityInstance> selectHistoricAcctivityList(String instanceId) {
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .activityType("userTask")
                .processInstanceId(instanceId)
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .asc()
                .list();
        return list;
    }

    @Override
    public String getComment(String taskId) {
        List<Comment> taskComments = taskService.getTaskComments(taskId);
        if (taskComments!=null && taskComments.size()>0){
            return taskComments.get(0).getFullMessage();
        }else {
            return "";
        }
    }
}
